home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-08-16 | 28.6 KB | 894 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWScrolr.cpp
- // Release Version: $ ODF 1 $
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWFrameW.hpp"
-
- #ifndef FWSCROLR_H
- #include "FWScrolr.h"
- #endif
-
- #ifndef FWPART_H
- #include "FWPart.h"
- #endif
-
- #ifndef FWFRAME_H
- #include "FWFrame.h"
- #endif
-
- #ifndef FWSCLNOT_H
- #include "FWSclNot.h"
- #endif
-
- #ifndef FWITERS_H
- #include "FWIters.h"
- #endif
-
- #ifndef FWUTIL_H
- #include "FWUtil.h"
- #endif
-
- #ifndef FWSCLBAR_H
- #include "FWSclBar.h"
- #endif
-
- #ifndef FWNOTDEF_H
- #include "FWNotDef.h"
- #endif
-
- #ifndef FWCONTXT_H
- #include "FWContxt.h"
- #endif
-
- // ----- Foundation Layer -----
-
- #ifndef FWAROPER_H
- #include "FWArOper.h"
- #endif
-
- // ----- OS Layer -----
-
- #ifndef FWODGEOM_H
- #include "FWODGeom.h"
- #endif
-
- #ifndef SLMIXOS_H
- #include "SLMixOS.h"
- #endif
-
- // ----- OpenDoc Includes -----
-
- #ifndef SOM_ODFacet_xh
- #include <Facet.xh>
- #endif
-
- #ifndef SOM_ODSession_xh
- #include <ODSessn.xh>
- #endif
-
- #ifndef SOM_ODTransform_xh
- #include <Trnsform.xh>
- #endif
-
- #ifndef SOM_ODWindow_xh
- #include <Window.xh>
- #endif
-
- #if defined(__MWERKS__) && GENERATING68K
- // A hack to work around a bug
- #pragma import list somGetGlobalEnvironment
- #endif
-
- //========================================================================================
- // RunTime Info
- //========================================================================================
-
- #ifdef FW_BUILD_MAC
- #pragma segment FW_FrameSegment
- #endif
-
- //========================================================================================
- // CLASS FW_CPrivBaseScroller
- //========================================================================================
-
- FW_DEFINE_CLASS_M0(FW_CPrivBaseScroller)
-
- // This class is archivable, but we provide the archiving implementation in a separate
- // translation unit in order to enable deadstripping of the archiving-related code
- // in parts that do not use archiving with this class.
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBaseScroller::FW_CPrivBaseScroller
- //----------------------------------------------------------------------------------------
-
- FW_CPrivBaseScroller::FW_CPrivBaseScroller()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivBaseScroller::~FW_CPrivBaseScroller
- //----------------------------------------------------------------------------------------
-
- FW_CPrivBaseScroller::~FW_CPrivBaseScroller()
- {
- }
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CPrivBaseScroller::PrivCheckFrame
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivBaseScroller::PrivCheckFrame(Environment* ev) const
- {
- FW_UNUSED(ev);
- // Nothing to do. See FW_CScrollBarScroller::PrivCheckFrame
- }
- #endif
-
- //========================================================================================
- // CLASS FW_CScroller
- //========================================================================================
-
- FW_DEFINE_AUTO(FW_CScroller)
- FW_DEFINE_CLASS_M1(FW_CScroller, FW_CPrivBaseScroller)
-
- // This class is archivable, but we provide the archiving implementation in a separate
- // translation unit in order to enable deadstripping of the archiving-related code
- // in parts that do not use archiving with this class.
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::FW_CScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScroller::FW_CScroller(Environment* ev, FW_CFrame* frame) :
- FW_CPrivBaseScroller(),
- FW_MReceiver(),
- fFrame(frame),
- fAutoScrollIncrement(FW_kZeroPoint), // By default no autoscroll
- fAutoScrollInset(FW_IntToFixed(5)),
- fLastAutoScrollTick(0)
- {
- FW_UNUSED(ev);
- FW_ASSERT(fFrame);
-
- FW_END_CONSTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::FW_CScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScroller::FW_CScroller(Environment* ev) :
- FW_CPrivBaseScroller(),
- FW_MReceiver(),
- fFrame(0),
- fAutoScrollIncrement(FW_kZeroPoint), // By default no autoscroll
- fAutoScrollInset(FW_IntToFixed(5)),
- fLastAutoScrollTick(0)
- {
- FW_UNUSED(ev);
- FW_END_CONSTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::~FW_CScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScroller::~FW_CScroller()
- {
- FW_START_DESTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::RegisterScrollBar
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::RegisterScrollNotifier(Environment* ev, FW_MNotifier* notifier)
- {
- FW_UNUSED(ev);
- // create the interest for the scroll notification
- AddInterest(FW_CInterest(notifier, FW_kScrollMsg));
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::UnregisterScrollNotifier
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::UnregisterScrollNotifier(Environment* ev, FW_MNotifier* notifier)
- {
- FW_UNUSED(ev);
- FW_CInterest interest(notifier, FW_kScrollMsg);
- RemoveInterest(interest);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::HandleNotification
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::HandleNotification(Environment* ev, const FW_CNotification& notification)
- {
- if (notification.GetMessage() == FW_kScrollMsg)
- {
- const FW_CScrollNotification& scrollNfy = (FW_CScrollNotification&) notification;
-
- FW_CPoint delta;
- delta[scrollNfy.GetDirection(ev)] = -scrollNfy.GetDelta(ev);
-
- PrivChangeOffset(ev,
- delta,
- scrollNfy.ShouldScroll(ev)); // I don't want to update right now
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::ScrollDraw
- //----------------------------------------------------------------------------------------
- // [HLX] Need a try block
-
- void FW_CScroller::ScrollDraw(Environment* ev, ODFacet* facet, const FW_CPoint& by)
- {
- #ifdef FW_BUILD_MAC
- ODPlatformWindow platformWindow = facet->GetWindow(ev)->GetPlatformWindow(ev);
-
- GrafPtr port;
- ::GetPort(&port);
- ::SetPort(platformWindow);
- Point origin;
- origin.h = platformWindow->portRect.left;
- origin.v = platformWindow->portRect.top;
- ODRgnHandle clipRgn = ::NewRgn();
- ::GetClip(clipRgn);
-
- ::SetOrigin(0, 0);
-
- FW_CAcquiredODShape aqScrollShape = PrivAcquireContentScrollShape(ev, (by.x != FW_kFixed0), (by.y != FW_kFixed0));
-
- // converts to window coordinates
- FW_CAcquiredODTransform aqWindowFrameTransform = facet->AcquireWindowFrameTransform(ev, NULL);
- aqScrollShape->Transform(ev, aqWindowFrameTransform);
-
- FW_CPlatformRect platformRect = FW_GetShapeBoundingBox(ev, aqScrollShape);
-
- // get clip shape in window coordinates & intersect with scrollShape
- FW_CAcquiredODShape aqAggregateClipShape = FW_CopyAndRelease(ev, facet->AcquireAggregateClipShape(ev, NULL));
- aqAggregateClipShape->Transform(ev, aqWindowFrameTransform);
-
- aqAggregateClipShape->Intersect(ev, aqScrollShape);
-
- RgnHandle aggregateClipRgn = aqAggregateClipShape->GetQDRegion(ev);
- ::SetClip(aggregateClipRgn);
-
- RgnHandle invalidRgn = ::NewRgn(); // will be adopted by aqInvalidShape. No need to dispose it
- ::ScrollRect(&platformRect, by.IntX(), by.IntY(), invalidRgn);
-
- FW_CAcquiredODShape aqInvalidShape = ::FW_NewODShape(ev, invalidRgn);
- aqInvalidShape->InverseTransform(ev, aqWindowFrameTransform);
-
- // ----- Validating all the embedded facets seems to make it a little bit faster
- // FW_CFacetIterator ite(ev, facet, kODChildrenOnly, kODFrontToBack);
- // for (ODFacet* embeddedFacet = ite.First(ev); ite.IsNotComplete(ev); embeddedFacet = ite.Next(ev))
- // {
- // embeddedFacet->Validate(ev, NULL, NULL);
- // }
-
- // ----- Update the facet -----
- facet->Invalidate(ev, aqInvalidShape, NULL);
- facet->GetWindow(ev)->Update(ev);
-
- ::SetPort(platformWindow);
- ::SetClip(clipRgn);
- ::DisposeRgn(clipRgn);
- ::SetOrigin(-origin.h, -origin.v);
- ::SetPort(port);
- #endif
-
- #ifdef FW_BUILD_WIN
- FW_DEBUG_MESSAGE("Needs to be redone");
- #endif
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::ScaleBy
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::ScaleBy(Environment* ev, const FW_CPoint& scaling, FW_CGraphicContext* gc)
- {
- FW_ASSERT(scaling.x != FW_kFixed0 && scaling.y != FW_kFixed0);
-
- FW_CAcquiredODTransform aqInternal = fFrame->AcquireInternalTransform(ev);
- FW_CPoint contentLocation = fFrame->PrivGetContentViewOffset(ev);
-
- aqInternal->MoveBy(ev, (ODPoint*)&(-contentLocation));
-
- FW_CPoint prevScaling;
- aqInternal->GetScale(ev, (ODPoint*)&prevScaling);
- aqInternal->ScaleDownBy(ev, (ODPoint*)&prevScaling);
-
- aqInternal->ScaleBy(ev, (ODPoint*)&scaling);
- aqInternal->MoveBy(ev, (ODPoint*)&contentLocation);
-
- fFrame->ChangeInternalTransform(ev, aqInternal);
-
- UpdateScrollParameters(ev);
-
- if (gc)
- gc->Reset();
-
- fFrame->Invalidate(ev); // Invalidate the whole frame
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::PrivChangeOffset
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::PrivChangeOffset(Environment* ev, const FW_CPoint& offset, FW_Boolean scroll)
- {
- FW_CPoint temp(offset);
-
- FW_CAcquiredODTransform aqFrameInternal = fFrame->AcquireInternalTransform(ev);
-
- FW_CPoint scale;
- aqFrameInternal->GetScale(ev, (ODPoint*)&scale);
- temp.x *= scale.x;
- temp.y *= scale.y;
- aqFrameInternal->MoveBy(ev, (ODPoint*)&temp);
-
- fFrame->ChangeInternalTransform(ev, aqFrameInternal);
-
- if (scroll)
- {
- // ------ Scroll all Facets of the frame
- FW_CFrameFacetIterator ite(ev, fFrame);
- for (ODFacet* facet = ite.First(ev); ite.IsNotComplete(ev); facet = ite.Next(ev))
- {
- this->ScrollDraw(ev, facet, temp);
- }
- }
-
- ScrollPositionChanged(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::UpdateScrollParameters
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::UpdateScrollParameters(Environment* ev, FW_Boolean notify)
- {
- FW_UNUSED(ev);
- FW_UNUSED(notify);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::ScrollPositionChanged
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::ScrollPositionChanged(Environment* ev)
- {
- FW_UNUSED(ev);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::InitializeAutoScroll
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::InitializeAutoScroll(Environment* ev)
- {
- FW_UNUSED(ev);
-
- fAutoScrollStage = kOutStage;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::GetScrollUnits
- //----------------------------------------------------------------------------------------
- // GetScrollUnits by default returns 1/10 of the size of the visible content for minor and
- // the size of the visible content for major
-
- void FW_CScroller::GetScrollUnits(Environment* ev, FW_Fixed& minor, FW_Fixed& major, FW_XYSelector direction)
- {
- FW_CPoint visibleContentSize = fFrame->GetContentView(ev)->GetBoundsInContent(ev).Size();
-
- minor = FW_IntToFixed(FW_FixedToInt(visibleContentSize[direction]) / 10);
- major = FW_RoundedToInt(visibleContentSize[direction]);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_PrivLimitScrolling
- //----------------------------------------------------------------------------------------
- // Don't forget positive offset means we are scrolling down so the scrollingArea is going
- // up in the extent
-
- static void FW_PrivLimitScrolling(const FW_CPoint& extent, const FW_CRect& scrollingArea, FW_CPoint& scrollBy)
- {
- if (scrollingArea.left - scrollBy.x < FW_kFixed0)
- scrollBy.x = scrollingArea.left;
- if (scrollingArea.right - scrollBy.x > extent.x)
- scrollBy.x = scrollingArea.right - extent.x;
-
- if (scrollingArea.top - scrollBy.y < FW_kFixed0)
- scrollBy.y = scrollingArea.top;
- if (scrollingArea.bottom - scrollBy.y > extent.y)
- scrollBy.y = scrollingArea.bottom - extent.y;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::AutoScrollOffset
- //----------------------------------------------------------------------------------------
-
- FW_CPoint FW_CScroller::AutoScrollOffset(Environment* ev,
- const FW_CPoint& currentPoint,
- unsigned long delay)
- {
- FW_CPoint scroll(FW_kZeroPoint);
-
- if (fAutoScrollIncrement != FW_kZeroPoint)
- {
- FW_CPoint delta;
-
- FW_CSuperView* contentView = fFrame->GetContentView(ev);
- FW_CRect content = contentView->GetBoundsInContent(ev);
- FW_CRect bounds(content);
-
- bounds.Inset(fAutoScrollInset);
-
- switch (::FW_RegionCode(currentPoint, bounds))
- {
- case 9:
- scroll = fAutoScrollIncrement;
- delta.x = currentPoint.x - content.left;
- delta.y = currentPoint.y - content.top;
- break;
- case 1:
- scroll.y = fAutoScrollIncrement.y;
- delta.y = currentPoint.y - content.top;
- break;
- case 5:
- scroll.x = -fAutoScrollIncrement.x;
- scroll.y = fAutoScrollIncrement.y;
- delta.x = content.right - currentPoint.x;
- delta.y = currentPoint.y - content.top;
- break;
- case 8:
- scroll.x = fAutoScrollIncrement.x;
- delta.x = currentPoint.x - content.left;
- break;
- case 4:
- scroll.x = -fAutoScrollIncrement.x;
- delta.x = content.right - currentPoint.x;
- break;
- case 10:
- scroll.x = fAutoScrollIncrement.x;
- scroll.y = -fAutoScrollIncrement.y;
- delta.x = currentPoint.x - content.left;
- delta.y = content.bottom - currentPoint.y;
- break;
- case 2:
- scroll.y = -fAutoScrollIncrement.y;
- delta.y = content.bottom - currentPoint.y;
- break;
- case 6:
- scroll = -fAutoScrollIncrement;
- delta.x = content.right - currentPoint.x;
- delta.y = content.bottom - currentPoint.y;
- break;
- }
-
- if (scroll != FW_kZeroPoint)
- {
- if (delta.x < FW_kFixed0)
- delta.x = FW_kFixed0;
- if (delta.y < FW_kFixed0)
- delta.y = FW_kFixed0;
-
- scroll.x = FW_RoundedToInt(((fAutoScrollInset - delta.x) * scroll.x) / fAutoScrollInset);
- scroll.y = FW_RoundedToInt(((fAutoScrollInset - delta.y) * scroll.y) / fAutoScrollInset);
-
- FW_PrivLimitScrolling(contentView->GetExtent(ev), content, scroll);
-
- if (delay != 0)
- {
- if (fAutoScrollStage == kOutStage)
- {
- fLastAutoScrollTick = ::FW_GetTickCount();
- fAutoScrollStage = kDelayStage;
- scroll = FW_kZeroPoint;
- }
- else if (fAutoScrollStage == kDelayStage)
- {
- if (::FW_GetTickCount() - fLastAutoScrollTick < delay)
- scroll = FW_kZeroPoint;
- else
- fAutoScrollStage = kScrollStage;
- }
- }
-
- // ----- Make sure that we don't scroll in an unwanted direction -----
- if (fAutoScrollIncrement.x == FW_kFixed0)
- scroll.x = FW_kFixed0;
- if (fAutoScrollIncrement.y == FW_kFixed0)
- scroll.y = FW_kFixed0;
- }
- else
- fAutoScrollStage = kOutStage;
- }
-
- return scroll;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::ScrollBy
- //----------------------------------------------------------------------------------------
- // a positive offset means we are scrolling down (down arrow)
-
- void FW_CScroller::ScrollBy(Environment* ev, const FW_CPoint& offset, FW_CGraphicContext* gc)
- {
- // ----- Validate the offset -----
- FW_CSuperView* contentView = fFrame->GetContentView(ev);
- FW_ASSERT(contentView);
-
- FW_CPoint scroll(offset);
- FW_PrivLimitScrolling(contentView->GetExtent(ev), contentView->GetBoundsInContent(ev), scroll);
-
- PrivScrollBy(ev, scroll, gc);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::PrivScrollBy
- //----------------------------------------------------------------------------------------
- // PrivScrollBy doesn't make any validation on the offset
-
- void FW_CScroller::PrivScrollBy(Environment* ev, const FW_CPoint& offset, FW_CGraphicContext* gc)
- {
- if (offset != FW_kZeroPoint)
- {
- // ----- We don't support scrolling in two directions at the same time so...
- if (offset.x != FW_kFixed0)
- PrivChangeOffset(ev, FW_CPoint(offset.x, FW_kFixed0), TRUE);
- if (offset.y != FW_kFixed0)
- PrivChangeOffset(ev, FW_CPoint(FW_kFixed0, offset.y), TRUE);
-
- if (gc)
- gc->Reset();
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::AutoScroll
- //----------------------------------------------------------------------------------------
- // currentPoint is in content coordinates
-
- void FW_CScroller::AutoScroll(Environment* ev,
- const FW_CPoint& currentPoint,
- FW_CGraphicContext* gc,
- unsigned long delay)
- {
- PrivScrollBy(ev, AutoScrollOffset(ev, currentPoint, delay), gc);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::PrivAcquireContentScrollShape
- //----------------------------------------------------------------------------------------
- // This returns the shape (in Frame coord.) composed of the ContentView + all the views
- // scrolling in X or Y with the content.
- // [LSD] if scroll is not purely X or Y we limit the shape to the ContentView for now.
- // Other views will have to scroll independantly
-
- ODShape* FW_CScroller::PrivAcquireContentScrollShape(Environment* ev, FW_Boolean horizontalScroll, FW_Boolean verticalScroll) const
- {
- FW_CSuperView* contentView = fFrame->GetContentView(ev);
- FW_ASSERT(contentView);
-
- // ----- Get the contentView first
- ODShape* scrollShape = ::FW_NewODShape(ev, FW_CRect(FW_kZeroPoint, contentView->GetSize(ev)));
- contentView->ViewToFrame(ev, scrollShape);
-
- // ----- Does not support both scrolling directions
- if ((!verticalScroll || !horizontalScroll) && (verticalScroll || horizontalScroll))
- fFrame->PrivAcquireContentScrollShape(ev, horizontalScroll, verticalScroll, scrollShape);
-
- return scrollShape;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::Flatten
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::Flatten(Environment* ev, FW_CWritableStream& stream) const
- {
- FW_CFrame* frame = fFrame;
- #ifdef FW_DEBUG
- FW_OObjectRegistry* registry = stream.GetRegistry();
- frame = (FW_CFrame*) registry->LookupByID(ev, FW_kPreregisteredFrameObject);
- FW_ASSERT(frame == fFrame);
- #else
- FW_UNUSED(ev);
- #endif
-
- FW_WRITE_DYNAMIC_OBJECT(stream, frame, FW_CFrame);
- stream << fAutoScrollInset;
- stream << fAutoScrollIncrement;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScroller::InitializeFromStream
- //----------------------------------------------------------------------------------------
-
- void FW_CScroller::InitializeFromStream(Environment* ev, FW_CReadableStream& stream)
- {
- #ifdef FW_DEBUG
- FW_OObjectRegistry* registry = stream.GetRegistry();
- FW_CFrame* frame = (FW_CFrame*) registry->LookupByID(ev, FW_kPreregisteredFrameObject);
- FW_ASSERT(frame != 0);
- #else
- FW_UNUSED(ev);
- #endif
-
- FW_READ_DYNAMIC_OBJECT(stream, &fFrame, FW_CFrame);
- FW_ASSERT(frame == fFrame);
-
- stream >> fAutoScrollInset;
- stream >> fAutoScrollIncrement;
- }
-
- //========================================================================================
- // CLASS FW_CScrollBarScroller
- //========================================================================================
-
- FW_DEFINE_AUTO(FW_CScrollBarScroller)
- FW_DEFINE_CLASS_M1(FW_CScrollBarScroller, FW_CScroller)
-
- // This class is archivable, but we provide the archiving implementation in a separate
- // translation unit in order to enable deadstripping of the archiving-related code
- // in parts that do not use archiving with this class.
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::FW_CScrollBarScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScrollBarScroller::FW_CScrollBarScroller(Environment* ev,
- FW_CFrame* frame,
- FW_CScrollBar* horzSB,
- FW_CScrollBar* vertSB) :
- FW_CScroller(ev, frame)
- {
- fScrollbars[FW_kHorizontal] = horzSB;
- fScrollbars[FW_kVertical] = vertSB;
-
- if (fScrollbars[FW_kHorizontal])
- RegisterScrollNotifier(ev, fScrollbars[FW_kHorizontal]);
- if (fScrollbars[FW_kVertical])
- RegisterScrollNotifier(ev, fScrollbars[FW_kVertical]);
-
- FW_END_CONSTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::FW_CScrollBarScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScrollBarScroller::FW_CScrollBarScroller(Environment* ev) :
- FW_CScroller(ev)
- {
- FW_END_CONSTRUCTOR
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::~FW_CScrollBarScroller
- //----------------------------------------------------------------------------------------
-
- FW_CScrollBarScroller::~FW_CScrollBarScroller()
- {
- FW_START_DESTRUCTOR
-
- // Don't delete the scroll bars, we don't own them! The containing gadget
- // or frame owns them.
-
- Environment* ev = ::somGetGlobalEnvironment();
-
- if (fScrollbars[FW_kHorizontal])
- UnregisterScrollNotifier(ev, fScrollbars[FW_kHorizontal]);
- if (fScrollbars[FW_kVertical])
- UnregisterScrollNotifier(ev, fScrollbars[FW_kVertical]);
- }
-
- //----------------------------------------------------------------------------------------
- // SetThumbPosition
- //----------------------------------------------------------------------------------------
-
- static void SetThumbPosition(Environment* ev, FW_CScrollBar* sb, FW_Fixed pos)
- {
- FW_Fixed oldPos = sb->GetScrollPos(ev);
- FW_Fixed newPos = FW_RoundedToInt(pos);
- if (oldPos != newPos)
- sb->SetScrollPos(ev, newPos);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::ScrollPositionChanged
- //----------------------------------------------------------------------------------------
-
- void FW_CScrollBarScroller::ScrollPositionChanged(Environment* ev)
- {
- FW_CSuperView* contentView = fFrame->GetContentView(ev);
- if (contentView == NULL)
- return;
-
- FW_CRect visibleContent = contentView->GetBoundsInContent(ev);
-
- FW_CScrollBar* sb = fScrollbars[FW_kVertical];
- if (sb != NULL)
- SetThumbPosition(ev, sb, visibleContent.top);
-
- sb = fScrollbars[FW_kHorizontal];
- if (sb != NULL)
- SetThumbPosition(ev, sb, visibleContent.left);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::PrivAdjustScrollBar
- //----------------------------------------------------------------------------------------
-
- FW_Boolean FW_CScrollBarScroller::PrivAdjustScrollBar(Environment* ev,
- FW_XYSelector direction,
- FW_Fixed visibleContent,
- FW_Fixed contentExtent,
- FW_Fixed contentOffset,
- FW_Boolean notify)
- {
- FW_CScrollBar* sb = fScrollbars[direction];
- if (sb == NULL)
- return FALSE;
-
- FW_Fixed oldPos = sb->GetScrollPos(ev);
- FW_Fixed scrollMin = sb->GetScrollMin(ev);
-
- // ----- Update scrollbar Major and Minor scroll units
- FW_Fixed minor, major;
- GetScrollUnits(ev, minor, major, direction);
-
- sb->SetMinorScrollUnits(ev, minor);
- sb->SetMajorScrollUnits(ev, major);
-
- // ----- calculate the maximum
- FW_Fixed maxOffset = FW_RoundedToInt(FW_Maximum(contentExtent - visibleContent, FW_kFixed0));
-
- sb->SetScrollMax(ev, scrollMin + maxOffset);
-
- // ----- Calculate the new position -----
- FW_Fixed newPos = FW_RoundedToInt(FW_Minimum(contentOffset, maxOffset));
-
- FW_Boolean positionChanged = (newPos != oldPos);
-
- if (newPos < scrollMin)
- newPos = scrollMin;
-
- if (positionChanged)
- {
- sb->SetScrollPos(ev, maxOffset, newPos);
- newPos = sb->GetScrollPos(ev); // I need to do that because of rounding
-
- if (notify)
- sb->ScrollPositionChanged(ev, newPos - oldPos, FALSE); // Don't scroll
- }
-
- return positionChanged;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::UpdateScrollParameters
- //----------------------------------------------------------------------------------------
-
- void FW_CScrollBarScroller::UpdateScrollParameters(Environment* ev, FW_Boolean notify)
- {
- FW_CSuperView* contentView = fFrame->GetContentView(ev);
- if (contentView == NULL)
- return;
-
- FW_CRect visibleContent = contentView->GetBoundsInContent(ev);
- FW_CPoint extent = contentView->GetExtent(ev);
-
- if (PrivAdjustScrollBar(ev, FW_kVertical, visibleContent.Height(), extent.y, visibleContent.top, notify))
- {
- FW_CAcquiredODShape invalidShape = PrivAcquireContentScrollShape(ev, FALSE, TRUE);
- fFrame->GetODFrame(ev)->Invalidate(ev, invalidShape, NULL);
- }
-
- if (PrivAdjustScrollBar(ev, FW_kHorizontal, visibleContent.Width(), extent.x, visibleContent.left, notify))
- {
- FW_CAcquiredODShape invalidShape = PrivAcquireContentScrollShape(ev, TRUE, FALSE);
- fFrame->GetODFrame(ev)->Invalidate(ev, invalidShape, NULL);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::RemoveScrollBar
- //----------------------------------------------------------------------------------------
- // This doesn't delete the scrollbar view itself
-
- void FW_CScrollBarScroller::RemoveScrollBar(Environment* ev, FW_XYSelector direction)
- {
- FW_UNUSED(ev);
- FW_CScrollBar* sb = fScrollbars[direction];
- if (sb == NULL)
- return;
-
- // Remove the connection first
- RemoveInterest(FW_CInterest(sb, FW_kScrollMsg));
-
- fScrollbars[direction] = NULL;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::Flatten
- //----------------------------------------------------------------------------------------
-
- void FW_CScrollBarScroller::Flatten(Environment* ev, FW_CWritableStream& stream) const
- {
- FW_CScroller::Flatten(ev, stream);
- ODID horizScrollBarID = kODNULLID;
- ODID vertScrollBarID = kODNULLID;
-
- if (fScrollbars[FW_kHorizontal])
- horizScrollBarID = fScrollbars[FW_kHorizontal]->GetViewId(ev);
- if (fScrollbars[FW_kVertical])
- vertScrollBarID = fScrollbars[FW_kVertical]->GetViewId(ev);
-
- stream << horizScrollBarID << vertScrollBarID;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::InitializeFromStream
- //----------------------------------------------------------------------------------------
-
- void FW_CScrollBarScroller::InitializeFromStream(Environment* ev, FW_CReadableStream& stream)
- {
- FW_CScroller::InitializeFromStream(ev, stream);
-
- ODID horizScrollBarID;
- ODID vertScrollBarID;
- stream >> horizScrollBarID >> vertScrollBarID;
-
- FW_CView* hScrollBarView = NULL;
- if (horizScrollBarID != kODNULLID)
- hScrollBarView = fFrame->FindViewById(ev, horizScrollBarID);
-
- FW_CView* vScrollBarView = NULL;
- if (vertScrollBarID != kODNULLID)
- vScrollBarView = fFrame->FindViewById(ev, vertScrollBarID);
-
- fScrollbars[FW_kHorizontal] = FW_DYNAMIC_CAST(FW_CScrollBar, hScrollBarView);
- fScrollbars[FW_kVertical] = FW_DYNAMIC_CAST(FW_CScrollBar, vScrollBarView);
-
- if (fScrollbars[FW_kHorizontal])
- RegisterScrollNotifier(ev, fScrollbars[FW_kHorizontal]);
-
- if (fScrollbars[FW_kVertical])
- RegisterScrollNotifier(ev, fScrollbars[FW_kVertical]);
- }
-
- #ifdef FW_DEBUG
- //----------------------------------------------------------------------------------------
- // FW_CScrollBarScroller::PrivCheckFrame
- //----------------------------------------------------------------------------------------
-
- void FW_CScrollBarScroller::PrivCheckFrame(Environment* ev) const
- {
- // We cannot authorize frames to use a scroller with scrollbars in case they don't have
- // a separate content view, because the scrollbars will end up moving with the rest of
- // frame's content! A frame which is its own content view can only use a basic
- // FW_CScroller instance, which can be scrolled with a hand-scrolling or auto-scrolling
- // mechanism.
-
- if (fFrame->IsContentView(ev))
- {
- FW_DEBUG_MESSAGE("Cannot use a ScrollBarScroller here, create a separate content view");
- }
-
- }
- #endif
-